"""
模式匹配服务 - 专职负责模式匹配和URL构建
"""

import os
import json
import yaml
import logging
from typing import Dict, List, Tuple, Optional

from .types import OperationResult


logger = logging.getLogger(__name__)


class PatternMatchingService:
    """模式匹配服务"""
    
    def __init__(self, registry_base: str = None, config_dir: str = None):
        self.logger = logging.getLogger(self.__class__.__name__)
        
        # 默认配置
        self.registry_base = registry_base or "crpi-axr6nxua9k92sqiz.cn-hangzhou.personal.cr.aliyuncs.com/mobox-docker"
        self.config_dir = config_dir or "/home/mobox/mobox_dashboard/config"
        
        # 加载模式匹配配置
        self.patterns = self._load_pattern_config()
    
    def build_full_image_url(self, base_image: str) -> str:
        """
        基于基础镜像信息构建完整的镜像URL
        
        Args:
            base_image: 基础镜像，如 "mobox-python-hardware:latest"
            
        Returns:
            str: 完整的镜像URL
        """
        if not base_image:
            raise ValueError("base_image不能为空")
        
        # 如果已经是完整URL，直接返回
        if base_image.startswith('http') or '/' in base_image.split(':')[0]:
            return base_image
        
        return f"{self.registry_base}/{base_image}"
    
    def select_compose_file(self, image_name: str) -> str:
        """
        根据镜像名称模式匹配选择合适的docker-compose文件
        
        Args:
            image_name: 镜像名称
            
        Returns:
            str: docker-compose文件路径
        """
        if not image_name:
            return self._get_default_compose_file()
        
        # 提取镜像名称（去除标签和注册表URL）
        base_name = self._extract_image_base_name(image_name)
        
        # 按优先级进行模式匹配
        for pattern_config in self.patterns:
            pattern = pattern_config['pattern']
            compose_file = pattern_config['compose_file']
            
            if pattern.lower() in base_name.lower():
                full_path = os.path.join(self.config_dir, compose_file)
                
                # 检查文件是否存在
                if os.path.exists(full_path):
                    self.logger.info(f"匹配模式 '{pattern}' -> {compose_file}")
                    return full_path
                else:
                    self.logger.warning(f"期望的compose文件不存在: {full_path}")
        
        # 没有匹配到，使用默认配置
        default_file = self._get_default_compose_file()
        self.logger.info(f"未匹配到特定模式，使用默认配置: {default_file}")
        return default_file
    
    def extract_container_name_from_compose(self, compose_file_path: str) -> Optional[str]:
        """
        从docker-compose文件中提取容器名称
        
        Args:
            compose_file_path: compose文件路径
            
        Returns:
            Optional[str]: 容器名称
        """
        try:
            if not os.path.exists(compose_file_path):
                self.logger.warning(f"Compose文件不存在: {compose_file_path}")
                return None
            
            with open(compose_file_path, 'r', encoding='utf-8') as f:
                compose_data = yaml.safe_load(f)
            
            services = compose_data.get('services', {})
            if not services:
                self.logger.warning(f"Compose文件中没有找到服务定义: {compose_file_path}")
                return None
            
            # 获取第一个服务的容器名称
            first_service = next(iter(services.values()))
            container_name = first_service.get('container_name')
            
            if container_name:
                return container_name
            
            # 如果没有明确指定container_name，使用服务名
            service_name = next(iter(services.keys()))
            return service_name
            
        except Exception as e:
            self.logger.error(f"解析compose文件失败: {e}")
            return None
    
    def get_pattern_info(self, image_name: str) -> Dict[str, str]:
        """
        获取镜像匹配的模式信息
        
        Args:
            image_name: 镜像名称
            
        Returns:
            Dict[str, str]: 模式信息
        """
        base_name = self._extract_image_base_name(image_name)
        
        for pattern_config in self.patterns:
            pattern = pattern_config['pattern']
            
            if pattern.lower() in base_name.lower():
                return {
                    'pattern': pattern,
                    'compose_file': pattern_config['compose_file'],
                    'description': pattern_config.get('description', ''),
                    'matched': True
                }
        
        return {
            'pattern': 'default',
            'compose_file': self._get_default_compose_file_name(),
            'description': '默认配置',
            'matched': False
        }
    
    def validate_compose_file(self, compose_file_path: str) -> OperationResult:
        """
        验证docker-compose文件的有效性
        
        Args:
            compose_file_path: compose文件路径
            
        Returns:
            OperationResult: 验证结果
        """
        try:
            if not os.path.exists(compose_file_path):
                return OperationResult(
                    success=False,
                    message=f"Compose文件不存在: {compose_file_path}",
                    error="File not found"
                )
            
            with open(compose_file_path, 'r', encoding='utf-8') as f:
                compose_data = yaml.safe_load(f)
            
            # 基本结构验证
            if not isinstance(compose_data, dict):
                return OperationResult(
                    success=False,
                    message="Compose文件格式无效：根节点不是字典",
                    error="Invalid YAML structure"
                )
            
            if 'services' not in compose_data:
                return OperationResult(
                    success=False,
                    message="Compose文件缺少services节点",
                    error="Missing services section"
                )
            
            services = compose_data['services']
            if not services:
                return OperationResult(
                    success=False,
                    message="Compose文件中没有定义服务",
                    error="No services defined"
                )
            
            # 验证每个服务的基本配置
            for service_name, service_config in services.items():
                if not service_config.get('image'):
                    return OperationResult(
                        success=False,
                        message=f"服务 {service_name} 缺少image配置",
                        error=f"Service {service_name} missing image"
                    )
            
            return OperationResult(
                success=True,
                message="Compose文件验证通过",
                details={
                    'file_path': compose_file_path,
                    'services_count': len(services),
                    'services': list(services.keys())
                }
            )
            
        except yaml.YAMLError as e:
            return OperationResult(
                success=False,
                message=f"Compose文件YAML格式错误: {str(e)}",
                error=f"YAML parse error: {str(e)}"
            )
        except Exception as e:
            return OperationResult(
                success=False,
                message=f"验证Compose文件时发生错误: {str(e)}",
                error=str(e)
            )
    
    def _load_pattern_config(self) -> List[Dict[str, str]]:
        """加载模式匹配配置"""
        config_file = os.path.join(self.config_dir, 'pattern_matching.json')
        
        # 默认模式配置
        default_patterns = [
            {
                'pattern': 'python',
                'compose_file': 'docker-compose-python.yml',
                'description': 'Python开发环境'
            },
            {
                'pattern': 'blockly',
                'compose_file': 'docker-compose-blockly.yml',
                'description': 'Blockly图形化编程'
            },
            {
                'pattern': 'hardware',
                'compose_file': 'docker-compose-hardware.yml',
                'description': '硬件控制平台'
            },
            {
                'pattern': 'notebook',
                'compose_file': 'docker-compose-notebook.yml',
                'description': 'Jupyter Notebook环境'
            },
            {
                'pattern': 'jupyter',
                'compose_file': 'docker-compose-jupyter.yml',
                'description': 'Jupyter实验环境'
            }
        ]
        
        try:
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    config_data = json.load(f)
                    patterns = config_data.get('patterns', default_patterns)
                    self.logger.info(f"加载模式匹配配置: {len(patterns)}个模式")
                    return patterns
        except Exception as e:
            self.logger.warning(f"加载模式匹配配置失败，使用默认配置: {e}")
        
        return default_patterns
    
    def _extract_image_base_name(self, image_name: str) -> str:
        """提取镜像基础名称"""
        # 移除注册表URL部分
        if '/' in image_name:
            image_name = image_name.split('/')[-1]
        
        # 移除标签部分
        if ':' in image_name:
            image_name = image_name.split(':')[0]
        
        return image_name
    
    def _get_default_compose_file(self) -> str:
        """获取默认compose文件的完整路径"""
        default_files = [
            'docker-compose-python.yml',
            'docker-compose.yml',
            'docker-compose-default.yml'
        ]
        
        for filename in default_files:
            full_path = os.path.join(self.config_dir, filename)
            if os.path.exists(full_path):
                return full_path
        
        # 如果都不存在，返回python版本的路径（后续会处理文件不存在的情况）
        return os.path.join(self.config_dir, 'docker-compose-python.yml')
    
    def _get_default_compose_file_name(self) -> str:
        """获取默认compose文件名"""
        return os.path.basename(self._get_default_compose_file())